package integral

import (
	"context"
	"strconv"
	"strings"

	"mall/common/globalkey"
	"mall/common/jwt"
	"mall/common/resultx"
	"mall/common/utils/pointy"
	"mall/service/forum/api/internal/svc"
	"mall/service/forum/api/internal/types"
	"mall/service/forum/api/internal/utils/parse"
	"mall/service/product/rpc/productclient"
	"mall/service/user/rpc/userclient"

	"github.com/zeromicro/go-zero/core/logx"
)

type GetProductLogListLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// 获取香评列表,首页多香评展示
func NewGetProductLogListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetProductLogListLogic {
	return &GetProductLogListLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *GetProductLogListLogic) GetProductLogList(
	req *types.IntegralExchangeProductLogListReq,
	headers *[]*types.Header,
) (*types.IntegralExchangeProductLogListResp, error) {
	page, pageSize := parse.ParsePageInfo(
		req.Current,
		req.PageSize,
		l.svcCtx.Config.Query.DefaultAmount,
		l.svcCtx.Config.Query.MaxAmount,
	)

	userId := jwt.GetUserId(l.ctx)
	if userId == 0 {
		return nil, resultx.NewErrCode(resultx.TOKEN_EXPIRE_ERROR)
	}

	filters := []string{"UserId,equalTo:" + strconv.FormatUint(userId, 10)}
	preload := "userIntegralTransactionLog:Id,ProductId,SkuId"
	preload += ",OrderId,OrderSn,Point,Status,CreatedAt"
	eagerLoad := "userIntegralTransactionLog:total"

	platformId := globalkey.ThirdPartyPlatformWechatMini
	res, err := l.svcCtx.UserRpc.GetIntegralExchangeProductLogList(l.ctx, &userclient.BaseListReq{
		Offset:     uint32((page - 1) * pageSize),
		Limit:      uint32(pageSize),
		Preload:    pointy.GetPointer(preload),
		EagerLoad:  pointy.GetPointer(eagerLoad),
		Filter:     pointy.GetPointer(strings.Join(filters, ";")),
		Sorter:     req.Sorter,
		VisitorId:  pointy.GetPointer(userId),
		PlatformId: pointy.GetPointer(platformId),
	})
	if err != nil {
		return nil, err
	}

	var hasNextPage bool
	var hasPreviousPage bool
	if res.HasNextPage != nil && *res.HasNextPage > 0 {
		hasNextPage = true
	}
	if res.HasPreviousPage != nil && *res.HasPreviousPage > 0 {
		hasPreviousPage = true
	}
	resp := &types.IntegralExchangeProductLogListResp{
		BaseListInfo: types.BaseListInfo{
			Total:           res.Total,
			Current:         page,
			PageSize:        pageSize,
			HasNextPage:     hasNextPage,
			HasPreviousPage: hasPreviousPage,
		},
	}

	if len(res.List) > 0 {
		var variationIds []string
		for _, v := range res.List {
			if v.SkuId != nil && *v.SkuId > 0 {
				variationIds = append(variationIds, strconv.FormatUint(*v.SkuId, 10))
			}
		}

		if len(variationIds) == 0 {
			return resp, nil
		}

		preload := "product:Id,ParentId,Title,Slug,ProductCode"
		eagerLoad := "product:productMeta,productVariation,productVariationMeta"
		preFilter := "Id,in:" + strings.Join(variationIds, ",")
		preFilterEntity := "productVariation"
		preFilter += ";Status,equalTo:" + strconv.FormatInt(int64(globalkey.StatusEnabled), 10)
		preload += ";productMeta:mediaUrl"
		preload += ";productVariation:Id,GemPrice,RetailPrice,CounterPrice,Weight,Status"
		preload += ";productVariationMeta:stock,mediaUrl,sku,skuKey"
		ret, err := l.svcCtx.ProductRpc.GetProductList(l.ctx, &productclient.BaseListReq{
			Preload:         pointy.GetPointer(preload),
			EagerLoad:       pointy.GetPointer(eagerLoad),
			PreFilterEntity: pointy.GetPointer(preFilterEntity),
			PreFilter:       pointy.GetPointer(preFilter),
		})
		if err != nil {
			return nil, err
		}

		idSkuMap := make(map[uint64]*types.IntegralExchangeProductLogInfo)
		if len(ret.List) > 0 {
			for _, item := range ret.List {
				if len(item.Skus) > 0 {
					var itemMediaUrl *string
					if len(item.Meta) > 0 {
						for _, m := range item.Meta {
							if m.Key == nil || m.Value == nil {
								continue
							}

							val := *m.Value
							switch *m.Key {
							case "mediaUrl":
								itemMediaUrl = pointy.GetPointer(val)
							}
						}
					}

					if len(item.Media) > 0 {
						for _, v := range item.Media {
							var url string
							if v.Url != nil && len(*v.Url) > 0 {
								url = *v.Url
							}
							if len(url) == 0 && v.Uri != nil && len(*v.Uri) > 0 {
								url = *v.Uri
							}
							if len(url) > 0 {
								itemMediaUrl = pointy.GetPointer(url)
								break
							}
						}
					}

					for _, sku := range item.Skus {
						if sku.Id == nil {
							continue
						}

						var mediaUrl *string
						if sku.MediaUrl != nil && len(strings.TrimSpace(*sku.MediaUrl)) > 0 {
							mediaUrl = sku.MediaUrl
						} else {
							mediaUrl = itemMediaUrl
						}

						idSkuMap[*sku.Id] = &types.IntegralExchangeProductLogInfo{
							ProductId:   item.Id,
							ProductCode: item.ProductCode,
							ProductName: item.Title,
							SkuId:       sku.Id,
							SkuCode:     sku.SkuCode,
							Sku:         sku.Label,
							Url:         mediaUrl,
						}
					}
				}
			}
		}

		for _, v := range res.List {
			var info *types.IntegralExchangeProductLogInfo
			if sku, ok := idSkuMap[*v.SkuId]; ok {
				info = sku
			}
			resp.List = append(resp.List, &types.IntegralExchangeProductLogInfo{
				Id:          v.Id,
				UserId:      v.UserId,
				ProductId:   info.ProductId,
				ProductCode: info.ProductCode,
				ProductName: info.ProductName,
				SkuId:       info.SkuId,
				SkuCode:     info.SkuCode,
				Sku:         info.Sku,
				Url:         info.Url,
				OrderId:     v.OrderId,
				OrderSn:     v.OrderSn,
				Points:      v.Points,
				Status:      v.Status,
				CreatedAt:   v.CreatedAt,
				UpdatedAt:   v.UpdatedAt,
			})
		}
	}

	return resp, nil
}
